home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / gcc / ixemlsrc.lha / ixemul / ixnet / res_query.c < prev    next >
C/C++ Source or Header  |  1996-03-13  |  8KB  |  290 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)res_query.c 5.11 (Berkeley) 3/6/91";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #define KERNEL
  39. #include "ixnet.h"
  40.  
  41. #include <sys/param.h>
  42. #include <netinet/in.h>
  43. #include <arpa/inet.h>
  44. #include <arpa/nameser.h>
  45. #include <netdb.h>
  46. #include <stdio.h>
  47. #include <errno.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <resolv.h>
  51. #include "utils.h"
  52.  
  53. #if PACKETSZ > 1024
  54. #define MAXPACKET    PACKETSZ
  55. #else
  56. #define MAXPACKET    1024
  57. #endif
  58.  
  59. /*
  60.  * Formulate a normal query, send, and await answer.
  61.  * Returned answer is placed in supplied buffer "answer".
  62.  * Perform preliminary check of answer, returning success only
  63.  * if no error is indicated and the answer count is nonzero.
  64.  * Return the size of the response on success, -1 on error.
  65.  * Error number is left in h_errno.
  66.  * Caller must parse answer and determine whether it answers the question.
  67.  */
  68. int
  69. res_query(char *name, int class, int type, u_char *answer, int anslen)
  70. {
  71.     char buf[MAXPACKET];
  72.     HEADER *hp;
  73.     int n;
  74.  
  75.     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  76.     return (-1);
  77.  
  78. #ifdef DEBUG
  79.     if (_res.options & RES_DEBUG)
  80.     printf("res_query(%s, %d, %d)\n", name, class, type);
  81. #endif
  82.     n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0,
  83.     NULL, buf, sizeof(buf));
  84.  
  85.     if (n <= 0) {
  86. #ifdef DEBUG
  87.     if (_res.options & RES_DEBUG)
  88.         printf("res_query: mkquery failed\n");
  89. #endif
  90.     h_errno = NO_RECOVERY;
  91.     return (n);
  92.     }
  93.  
  94.     n = res_send(buf, n, (char *)answer, anslen);
  95.  
  96.     if (n < 0) {
  97. #ifdef DEBUG
  98.     if (_res.options & RES_DEBUG)
  99.         printf("res_query: send error\n");
  100. #endif
  101.     h_errno = TRY_AGAIN;
  102.     return(n);
  103.     }
  104.  
  105.     hp = (HEADER *) answer;
  106.     if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
  107. #ifdef DEBUG
  108.     if (_res.options & RES_DEBUG)
  109.         printf("rcode = %d, ancount=%d\n", hp->rcode,
  110.  
  111.     ntohs(hp->ancount));
  112. #endif
  113.     switch (hp->rcode) {
  114.         case NXDOMAIN:
  115.         h_errno = HOST_NOT_FOUND;
  116.         break;
  117.  
  118.         case SERVFAIL:
  119.         h_errno = TRY_AGAIN;
  120.         break;
  121.  
  122.         case NOERROR:
  123.         h_errno = NO_DATA;
  124.         break;
  125.  
  126.         case FORMERR:
  127.         case NOTIMP:
  128.         case REFUSED:
  129.         default:
  130.         h_errno = NO_RECOVERY;
  131.         break;
  132.     }
  133.     return (-1);
  134.     }
  135.     return(n);
  136. }
  137.  
  138. /*
  139.  * Formulate a normal query, send, and retrieve answer in supplied buffer.
  140.  * Return the size of the response on success, -1 on error.
  141.  * If enabled, implement search rules until answer or unrecoverable failure
  142.  * is detected.  Error number is left in h_errno.
  143.  * Only useful for queries in the same name hierarchy as the local host
  144.  * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
  145.  */
  146. int
  147. res_search(char *name, int class, int type, u_char *answer, int anslen)
  148. {
  149.     register char *cp, **domain;
  150.     int n, ret, got_nodata = 0;
  151.     char *__hostalias();
  152.  
  153.     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  154.     return (-1);
  155.  
  156.     errno = 0;
  157.     h_errno = HOST_NOT_FOUND;            /* default, if we never query */
  158.     for (cp = name, n = 0; *cp; cp++)
  159.     if (*cp == '.')
  160.         n++;
  161.  
  162.     if (n == 0 && (cp = __hostalias(name)))
  163.     return (res_query(cp, class, type, answer, anslen));
  164.  
  165.     /*
  166.      * We do at least one level of search if
  167.      *        - there is no dot and RES_DEFNAME is set, or
  168.      *        - there is at least one dot, there is no trailing dot,
  169.      *          and RES_DNSRCH is set.
  170.      */
  171.     if ((n == 0 && _res.options & RES_DEFNAMES) ||
  172.     (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
  173.  
  174.     for (domain = _res.dnsrch; *domain; domain++) {
  175.         ret = res_querydomain(name, *domain, class, type, answer, anslen);
  176.         if (ret > 0)
  177.         return (ret);
  178.         /*
  179.          * If no server present, give up.
  180.          * If name isn't found in this domain,
  181.          * keep trying higher domains in the search list
  182.          * (if that's enabled).
  183.          * On a NO_DATA error, keep trying, otherwise
  184.          * a wildcard entry of another type could keep us
  185.          * from finding this entry higher in the domain.
  186.          * If we get some other error (negative answer or
  187.          * server failure), then stop searching up,
  188.          * but try the input name below in case it's fully-qualified.
  189.          */
  190.         if (errno == ECONNREFUSED) {
  191.         h_errno = TRY_AGAIN;
  192.         return (-1);
  193.         }
  194.  
  195.         if (h_errno == NO_DATA)
  196.         got_nodata++;
  197.  
  198.         if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
  199.         (_res.options & RES_DNSRCH) == 0)
  200.         break;
  201.     }
  202.     /*
  203.      * If the search/default failed, try the name as fully-qualified,
  204.      * but only if it contained at least one dot (even trailing).
  205.      * This is purely a heuristic; we assume that any reasonable query
  206.      * about a top-level domain (for servers, SOA, etc) will not use
  207.      * res_search.
  208.      */
  209.     if (n && (ret = res_querydomain(name, (char *)NULL, class, type,
  210.         answer, anslen)) > 0)
  211.         return (ret);
  212.  
  213.     if (got_nodata)
  214.         h_errno = NO_DATA;
  215.     return (-1);
  216. }
  217.  
  218. /*
  219.  * Perform a call on res_query on the concatenation of name and domain,
  220.  * removing a trailing dot from name if domain is NULL.
  221.  */
  222. int
  223. res_querydomain(char *name, char *domain, int class, int type,
  224.     u_char *answer, int anslen)
  225. {
  226.     char nbuf[2*MAXDNAME+2];
  227.     char *longname = nbuf;
  228.     int n;
  229.  
  230. #ifdef DEBUG
  231.     if (_res.options & RES_DEBUG)
  232.         printf("res_querydomain(%s, %s, %d, %d)\n",
  233.         name, domain, class, type);
  234. #endif
  235.     if (domain == NULL) {
  236.     /*
  237.      * Check for trailing '.';
  238.      * copy without '.' if present.
  239.      */
  240.     n = strlen(name) - 1;
  241.     if (name[n] == '.' && n < sizeof(nbuf) - 1) {
  242.         bcopy(name, nbuf, n);
  243.         nbuf[n] = '\0';
  244.     }
  245.     else
  246.         longname = name;
  247.     }
  248.     else
  249.     (void)sprintf(nbuf, "%.*s.%.*s",
  250.         MAXDNAME, name, MAXDNAME, domain);
  251.  
  252.     return (res_query(longname, class, type, answer, anslen));
  253. }
  254.  
  255. char *
  256. __hostalias(const char *name)
  257. {
  258.     register char *C1, *C2;
  259.     FILE *fp;
  260.     char *file, *getenv(), *strcpy(), *strncpy();
  261.     char buf[BUFSIZ];
  262.     static char abuf[MAXDNAME];
  263.  
  264.     file = getenv("HOSTALIASES");
  265.     if (file == NULL || (fp = fopen(file, "r")) == NULL)
  266.     return (NULL);
  267.  
  268.     buf[sizeof(buf) - 1] = '\0';
  269.     while (fgets(buf, sizeof(buf), fp)) {
  270.     for (C1 = buf; *C1 && !isspace(*C1); ++C1);
  271.     if (!*C1)
  272.         break;
  273.     *C1 = '\0';
  274.     if (!strcasecmp(buf, name)) {
  275.         while (isspace(*++C1))
  276.         ;
  277.         if (!*C1)
  278.         break;
  279.         for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2)
  280.         ;
  281.         abuf[sizeof(abuf) - 1] = *C2 = '\0';
  282.         (void)strncpy(abuf, C1, sizeof(abuf) - 1);
  283.         fclose(fp);
  284.         return (abuf);
  285.     }
  286.     }
  287.     fclose(fp);
  288.     return (NULL);
  289. }
  290.